package tools

import (
	"context"
	"fmt"
	"sync"
	"time"

	"github.com/rs/zerolog/log"
	"gorm.io/datatypes"
	"techoiceness.com/aiagent/llm-gateway/internal/entity"
	"techoiceness.com/aiagent/llm-gateway/internal/llm/types"
	"techoiceness.com/aiagent/llm-gateway/internal/repository"
)

// SimpleTool 简单工具接口
type SimpleTool interface {
	Name() string
	Description() string
	Execute(arguments string) (string, error)
	Definition() types.Tool
}

// ConfigurableTool 可配置工具接口
type ConfigurableTool interface {
	SimpleTool
	ReloadConfig() error
}

// ToolManager 工具管理器
type ToolManager struct {
	tools        map[string]SimpleTool
	toolsEnabled map[string]bool // 工具启用状态
	repository   repository.SimpleToolRepository
	mutex        sync.RWMutex
}

// NewToolManager 创建工具管理器
func NewToolManager(repo repository.SimpleToolRepository) *ToolManager {
	return &ToolManager{
		tools:        make(map[string]SimpleTool),
		toolsEnabled: make(map[string]bool),
		repository:   repo,
	}
}

// RegisterTool 注册工具
func (tm *ToolManager) RegisterTool(tool SimpleTool) error {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()

	// 直接注册到内存
	tm.tools[tool.Name()] = tool

	// 如果有数据库，保存到数据库并同步状态
	if tm.repository != nil {
		// 创建默认配置
		defaultConfig := datatypes.JSON("{}")

		toolEntity := &entity.Tool{
			Name:        tool.Name(),
			DisplayName: tool.Name(),
			Description: tool.Description(),
			IsEnabled:   true,
			Config:      &defaultConfig,
		}

		// 检查工具是否已存在
		if existingTool, err := tm.repository.GetToolByName(context.Background(), tool.Name()); err != nil {
			// 工具不存在，创建新的
			if err := tm.repository.CreateTool(context.Background(), toolEntity); err != nil {
				log.Error().
					Str("module", "ToolManager.RegisterTool").
					Str("tool_name", tool.Name()).
					Err(err).
					Msg("保存工具到数据库失败")
			}
			// 设置默认启用状态
			tm.toolsEnabled[tool.Name()] = true
		} else {
			// 工具已存在，更新信息（但保留状态和统计），并同步状态到内存
			existingTool.DisplayName = tool.Name()
			existingTool.Description = tool.Description()
			if err := tm.repository.UpdateTool(context.Background(), existingTool); err != nil {
				log.Error().
					Str("module", "ToolManager.RegisterTool").
					Str("tool_name", tool.Name()).
					Err(err).
					Msg("更新工具到数据库失败")
			}
			// 同步数据库状态到内存
			tm.toolsEnabled[tool.Name()] = existingTool.IsEnabled
		}
	} else {
		// 没有数据库时，默认启用
		tm.toolsEnabled[tool.Name()] = true
	}

	return nil
}

// GetTool 获取工具
func (tm *ToolManager) GetTool(name string) (SimpleTool, bool) {
	tm.mutex.RLock()
	defer tm.mutex.RUnlock()

	tool, exists := tm.tools[name]
	return tool, exists
}

// ListTools 列出所有工具
func (tm *ToolManager) ListTools() []SimpleTool {
	tm.mutex.RLock()
	defer tm.mutex.RUnlock()

	tools := make([]SimpleTool, 0, len(tm.tools))
	for _, tool := range tm.tools {
		tools = append(tools, tool)
	}
	return tools
}

// GetToolDefinitions 获取启用的工具定义
func (tm *ToolManager) GetToolDefinitions() []types.Tool {
	tm.mutex.RLock()
	defer tm.mutex.RUnlock()

	definitions := make([]types.Tool, 0, len(tm.tools))
	for name, tool := range tm.tools {
		if enabled, exists := tm.toolsEnabled[name]; exists && enabled {
			definitions = append(definitions, tool.Definition())
		}
	}
	return definitions
}

// ExecuteTool 执行工具
func (tm *ToolManager) ExecuteTool(name string, arguments string) (string, error) {
	tool, exists := tm.GetTool(name)
	if !exists {
		return "", fmt.Errorf("找不到工具: %s", name)
	}

	// 检查工具是否启用
	tm.mutex.RLock()
	enabled, enabledExists := tm.toolsEnabled[name]
	tm.mutex.RUnlock()

	if !enabledExists || !enabled {
		return "", fmt.Errorf("工具已禁用: %s", name)
	}

	start := time.Now()
	result, err := tool.Execute(arguments)
	duration := time.Since(start)

	// 更新使用统计
	if tm.repository != nil {
		if updateErr := tm.repository.UpdateToolUsage(context.Background(), name); updateErr != nil {
			log.Error().
				Str("module", "ToolManager.ExecuteTool").
				Str("tool_name", name).
				Err(updateErr).
				Msg("更新工具使用统计失败")
		}
	}

	log.Info().
		Str("module", "ToolManager.ExecuteTool").
		Str("tool_name", name).
		Dur("duration", duration).
		Bool("success", err == nil).
		Msg("工具执行成功")

	return result, err
}

// EnableTool 设置工具启用状态
func (tm *ToolManager) EnableTool(name string) error {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()

	// 检查工具是否存在
	if _, exists := tm.tools[name]; !exists {
		return fmt.Errorf("找不到工具: %s", name)
	}

	// 更新内存中的状态
	tm.toolsEnabled[name] = true

	// 如果有数据库，也更新数据库状态
	if tm.repository != nil {
		if toolEntity, err := tm.repository.GetToolByName(context.Background(), name); err == nil {
			toolEntity.IsEnabled = true
			if err := tm.repository.UpdateTool(context.Background(), toolEntity); err != nil {
				return fmt.Errorf("更新工具状态到数据库失败: %v", err)
			}
		}
	}

	log.Info().
		Str("module", "ToolManager.EnableTool").
		Str("tool_name", name).
		Msg("工具启用成功")

	return nil
}

// DisableTool 设置工具禁用状态
func (tm *ToolManager) DisableTool(name string) error {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()

	// 检查工具是否存在
	if _, exists := tm.tools[name]; !exists {
		return fmt.Errorf("找不到工具: %s", name)
	}

	// 更新内存中的状态
	tm.toolsEnabled[name] = false

	// 如果有数据库，也更新数据库状态
	if tm.repository != nil {
		if toolEntity, err := tm.repository.GetToolByName(context.Background(), name); err == nil {
			toolEntity.IsEnabled = false
			if err := tm.repository.UpdateTool(context.Background(), toolEntity); err != nil {
				return fmt.Errorf("更新工具状态到数据库失败: %v", err)
			}
		}
	}

	log.Info().
		Str("module", "ToolManager.DisableTool").
		Str("tool_name", name).
		Msg("Tool disabled")

	return nil
}

// IsToolEnabled 检查工具是否启用
func (tm *ToolManager) IsToolEnabled(name string) bool {
	tm.mutex.RLock()
	defer tm.mutex.RUnlock()

	enabled, exists := tm.toolsEnabled[name]
	return exists && enabled
}

// GetToolStats 获取工具统计信息
func (tm *ToolManager) GetToolStats(name string) (*entity.Tool, error) {
	if tm.repository == nil {
		return nil, fmt.Errorf("database repository not available")
	}

	return tm.repository.GetToolByName(context.Background(), name)
}

// ListToolStats 列出所有工具统计信息
func (tm *ToolManager) ListToolStats() ([]*entity.Tool, error) {
	if tm.repository == nil {
		return nil, fmt.Errorf("database repository not available")
	}

	return tm.repository.ListTools(context.Background())
}

// UpdateTool 更新工具
func (tm *ToolManager) UpdateTool(tool *entity.Tool) error {
	if tm.repository == nil {
		return fmt.Errorf("database repository not available")
	}
	return tm.repository.UpdateTool(context.Background(), tool)
}

// ReloadToolConfig 重新加载指定工具的配置
func (tm *ToolManager) ReloadToolConfig(name string) error {
	tm.mutex.Lock()
	defer tm.mutex.Unlock()

	// 检查工具是否存在于内存中
	tool, exists := tm.tools[name]
	if !exists {
		return fmt.Errorf("找不到工具: %s", name)
	}

	// 如果没有数据库连接，无法重新加载配置
	if tm.repository == nil {
		return fmt.Errorf("database repository not available")
	}

	// 从数据库获取最新配置
	toolEntity, err := tm.repository.GetToolByName(context.Background(), name)
	if err != nil {
		return fmt.Errorf("无法从数据库获取工具配置: %v", err)
	}

	// 根据工具类型重新初始化
	switch name {
	case "postgresql":
		// 对于PostgreSQL工具，需要重新创建实例以应用新配置
		if err := tm.reinitializePostgreSQLTool(tool, toolEntity); err != nil {
			return fmt.Errorf("重新初始化PostgreSQL工具失败: %v", err)
		}
	default:
		// 其他工具暂时不需要特殊处理
		log.Info().
			Str("module", "ToolManager.ReloadToolConfig").
			Str("tool_name", name).
			Msg("工具配置已重新加载（无需特殊处理）")
	}

	log.Info().
		Str("module", "ToolManager.ReloadToolConfig").
		Str("tool_name", name).
		Msg("工具配置重新加载成功")

	return nil
}

// reinitializePostgreSQLTool 重新初始化PostgreSQL工具
func (tm *ToolManager) reinitializePostgreSQLTool(tool SimpleTool, toolEntity *entity.Tool) error {
	// 检查工具是否实现了ConfigurableTool接口
	if configurableTool, ok := tool.(ConfigurableTool); ok {
		// 调用工具的ReloadConfig方法来重新加载配置
		if err := configurableTool.ReloadConfig(); err != nil {
			log.Error().
				Str("module", "ToolManager.ReloadToolConfig").
				Str("tool_name", tool.Name()).
				Err(err).
				Msg("重新加载PostgreSQL工具配置失败")
			return fmt.Errorf("重新加载配置失败: %w", err)
		}
	}

	log.Info().
		Str("module", "ToolManager.ReloadToolConfig").
		Str("tool_name", tool.Name()).
		Str("config", string(*toolEntity.Config)).
		Msg("PostgreSQL工具配置已更新并重新加载")

	return nil
}
